<?php

namespace app\services;

use app\payment\PayFactory;
use Carbon\Carbon;
use plugin\admin\app\model\ChannelName;
use plugin\admin\app\model\Order;
use plugin\admin\app\model\User;
use plugin\admin\app\model\UserPropertyLog;
use plugin\admin\app\model\UserWork;
use plugin\admin\app\model\Work;
use plugin\admin\app\model\WorkCategory;
use support\Log;

class WorkService
{
    public static function getAllCategories()
    {
        $res = WorkCategory::all(['id', 'name', 'icon']);

        foreach ($res as $value) {
            $value->icon = full_url($value->icon);
        }

        return $res;
    }

    public static function getChannelNames()
    {
        // 获取所有父级通道（parent_id 为 0 或 null）
        $parentChannels = ChannelName::where(function ($query) {
            $query->where('parent_id', 0)
                ->orWhereNull('parent_id');
        })
            ->select(['id', 'name', 'en_name'])
            ->get();

        // 获取所有子级通道
        $childChannels = ChannelName::where('parent_id', '>', 0)
            ->select(['id', 'name', 'en_name', 'parent_id'])
            ->get()
            ->groupBy('parent_id');

        // 构建二级结构
        foreach ($parentChannels as $parent) {
            $parent->children = $childChannels->get($parent->id, collect());
        }

        return $parentChannels;
    }

    public static function canPublishWork()
    {
        $userId = get_user_id();
        $user = User::find($userId);

        if (!$user) {
            throw new \Exception('用户未找到.');
        }

        if (!$user->is_vip && !$user->is_creator) {
            $workCount = Work::where('user_id', $userId)
                ->whereNull('delete_time')
                ->where('is_buy', 0)
                ->count();

            $limit = ConfigService::get('normal_member_work_count');

            if ($workCount >= $limit) {
                throw new \Exception("非VIP用户最多只能发布{$limit}个作品.");
            }
        }

        return true;
    }

    public static function add($name, $images, $url, $ossName, $no, $categoryId)
    {
        self::canPublishWork();

        if (empty($name) || empty($images) || empty($no)) {
            throw new \InvalidArgumentException('作品名称, 图片集, 作品编号和作品链接为必填项.');
        }

        $thumb = $images[0];
        $imagesJson = json_encode($images);
        $createdTime = Carbon::now();
        $userId = get_user_id();

        $work = new Work();
        $work->name = $name;
        $work->no = $no;
        $work->oss_name = $ossName;
        $work->thumb = $thumb;
        $work->images = $imagesJson;
        $work->url = $url;
        $work->category_id = empty($categoryId) ? null : $categoryId;
        $work->created_time = $createdTime;
        $work->user_id = $userId;

        $userInfo = User::find($userId);
        //        if ($userInfo['is_creator']) {
//            $work->status = Work::STATUS_PENDING;
//        } else {
        $work->status = Work::STATUS_APPROVED;
        //        }

        $work->save();

        return $work;
    }

    public static function getRecommendedWorks()
    {
        $works = Work::where('is_recommend', 1)
            ->whereNull('delete_time')
            ->where('is_public', 1)
            ->select(['id', 'name', 'thumb', 'url', 'views', 'price', 'sales'])
            ->limit(20)
            ->get();

        foreach ($works as $work) {
            $work->thumb = build_oss_url($work->thumb);
        }

        return $works;
    }

    public static function getCountIncludeDeleted()
    {
        $userId = get_user_id();
        return Work::where('user_id', $userId)
            ->where('is_buy', 0)
            ->count();
    }

    public static function getWorksByCategory($categoryId = 0, $page = 1, $length = 12, $keyword = '')
    {

        $query = Work::join('wa_user_profiles', 'wa_user_profiles.user_id', '=', 'wa_works.user_id')
            ->whereNull('wa_works.delete_time')
            ->where('wa_works.is_public', 1)
            ->where('wa_works.status', Work::STATUS_APPROVED)
            ->select([
                'wa_works.id',
                'wa_works.name',
                'wa_works.images',
                'wa_works.thumb',
                'wa_works.tags',
                'wa_works.url',
                'wa_works.views',
                'wa_works.price',
                'wa_works.sales',
                'wa_user_profiles.user_id as user_id',
                'wa_user_profiles.nickname as user_name',
                'wa_user_profiles.avatar as user_avatar'
            ]);

        if ($categoryId) {
            $query->where('wa_works.category_id', $categoryId);
        }

        if ($keyword) {
            $query->where('wa_works.name', 'like', "%{$keyword}%");
        }

        $works = $query->orderBy('id', 'desc')->paginate($length, ['*'], 'page', $page);

        foreach ($works as $work) {
            $work->user_avatar = full_url($work->user_avatar);
            $work->thumb = build_oss_url($work->thumb);

            $images = json_decode($work->images, true);

            foreach ($images as $key => $image) {
                $images[$key] = build_oss_url($image);
            }
            $work->images = $images;
        }

        return $works;
    }

    public static function getWorkDetailById($id)
    {
        if (empty($id)) {
            throw new \InvalidArgumentException('作品ID为必填项.');
        }

        $work = Work::join('wa_user_profiles', 'wa_user_profiles.user_id', '=', 'wa_works.user_id')
            ->where('wa_works.id', $id)
            ->where('wa_works.is_public', 1)
            ->whereNull('wa_works.delete_time')
            ->select([
                'wa_works.id',
                'wa_works.name',
                'wa_works.images',
                'wa_works.thumb',
                'wa_works.url',
                'wa_works.tags',
                'wa_works.oss_name',
                'wa_works.no',
                'wa_works.category_id',
                'wa_works.views',
                'wa_works.price',
                'wa_works.sales',
                'wa_works.is_public',
                'wa_works.status',
                'wa_works.reason',
                'wa_works.created_time',
                'wa_user_profiles.user_id as user_id',
                'wa_user_profiles.nickname as user_name',
                'wa_user_profiles.avatar as user_avatar'
            ])
            ->first();

        if (!$work) {
            throw new \Exception('作品未找到或已被删除.');
        }

        $work->views = $work->views + 1;
        $work->save();

        $workId = $work->id;

        $userWork = UserWork::where('user_id', get_user_id())->where('work_id', $id)->where('is_pay', 1)->first();

        $work->is_buy = $userWork ? 1 : 0;

        if ($work->user_id == get_user_id()) {
            $work->edit_url = build_edit_tools_url('edit', $workId);
            $work->preview_url = build_edit_tools_url('preview', $workId);
        } else {
            if ($work->is_buy) {
                $work->edit_url = build_edit_tools_url('edit', $userWork['new_work_id']);
                $work->preview_url = build_edit_tools_url('preview', $workId);
            }
        }

        $work->tags = json_decode($work->tags, true);
        $work->user_avatar = full_url($work->user_avatar);

        $work->thumb = build_oss_url($work->thumb);

        $images = json_decode($work->images, true);

        foreach ($images as $key => $image) {
            $images[$key] = build_oss_url($image);
        }
        $work->images = $images;

        return $work;
    }


    public static function getList($page, $length, $no = null, $type = 0)
    {
        $query = Work::select(['id', 'category_id', 'thumb', 'user_id', 'name', 'images', 'url', 'is_public', 'views', 'price', 'sales', 'oss_name', 'audit_time', 'status', 'created_time', 'no', 'reason', 'tags', 'is_buy']);

        if (!empty($type)) {
            if ($type == 1) {
                $query->where('is_public', 1)->where('is_buy', 0);
            } elseif ($type == 2) {
                $query->where('is_public', 0)->where('is_buy', 0);
            } else {
                $query->where('is_buy', 1);
            }
        }

        if (!empty($no)) {
            $query->where('no', 'like', '%' . $no . '%');
        }

        $query->where('user_id', get_user_id())->whereNull('delete_time');


        $works = $query->orderBy('id', 'desc')->paginate($length, ['*'], 'page', $page);

        foreach ($works as $work) {
            $work->share_url = build_edit_tools_url('preview', $work->id);
            $work->edit_url = build_edit_tools_url('edit', $work->id);
            $work->created_time = date('Y-m-d', strtotime($work['created_time']));

            $work->thumb = build_oss_url($work->thumb);

            $images = json_decode($work->images, true);

            foreach ($images as $key => $image) {
                $images[$key] = build_oss_url($image);
            }
            $work->images = $images;
        }


        return $works;
    }

    public static function editAttr($id, $isPublic = null, $isDelete = null, $price = null, $categoryId = 0, $tags = '', $name = '')
    {
        $work = Work::find($id);
        if (!$work) {
            throw new \Exception('作品未找到.');
        }

        $userId = get_user_id();
        if ($work->user_id !== $userId) {
            throw new \Exception('无权编辑此作品.');
        }

        $user = User::where('id', $userId)->first();

        if (!is_null($isPublic)) {
            //            if ($isPublic == 1 && $work->status != Work::STATUS_APPROVED) {
//                throw new \Exception('作品未审核通过，无法修改为公开.');
//            }

            if ($isPublic == 1 && !$user['is_creator']) {
                throw new \Exception('非创作者，无法修改为公开.');
            }

            if ($work['audit_time']) {

                if ($work['status'] == 2) {
                    $work->status = Work::STATUS_PENDING;
                } else {
                    $work->is_public = $isPublic;

                    if ($isPublic == 0) {
                        $work->audit_time = null;
                    }
                }
            } else {
                if ($isPublic == 1) {
                    $work->status = Work::STATUS_PENDING;
                } else {
                    $work->is_public = $isPublic;
                }
            }

        }

        if (!empty($isDelete)) {
            $work->delete_time = date('Y-m-d H:i:s');
        }

        if (!empty($price)) {
            $work->price = $price;
        }

        if (!empty($categoryId)) {
            $work->category_id = $categoryId;
        }

        if (!empty($tags)) {
            $work->tags = $tags;
        }

        if (!empty($name)) {
            $work->name = $name;
        }

        $work->save();

        return $work;
    }

    public static function edit($id, $images, $url, $name = null)
    {
        if (empty($id) || empty($images)) {
            throw new \InvalidArgumentException('作品ID, 图片集, 和作品链接为必填项.');
        }

        $work = Work::find($id);
        if (!$work) {
            throw new \Exception('作品未找到.');
        }

        $userId = get_user_id();
        if ($work->user_id !== $userId) {
            throw new \Exception('无权编辑此作品.');
        }

        $thumb = $images[0];
        $imagesJson = json_encode($images);
        $updatedTime = Carbon::now();

        if (!is_null($name)) {
            $work->name = $name;
        }

        $work->thumb = $thumb;
        $work->images = $imagesJson;
        $work->url = $url;

        $work->save();

        return $work;
    }


    public static function getDetail($id, $auth = true)
    {
        if (empty($id)) {
            throw new \InvalidArgumentException('作品ID为必填项.');
        }

        $work = Work::find($id, ['id', 'user_id', 'name', 'images', 'url', 'oss_name', 'no', 'category_id']);
        if (!$work) {
            throw new \Exception('作品未找到.');
        }

        $userId = get_user_id();
        if ($work->user_id !== $userId && $auth) {
            throw new \Exception('无权查看此作品.');
        }

        $work->images = json_decode($work->images, true);

        return $work;
    }

    public static function setToPublic($id)
    {
        return self::setPublicStatus($id, 1);
    }

    public static function setToPrivate($id)
    {
        return self::setPublicStatus($id, 0);
    }

    public static function setPublicStatus($id, $status)
    {
        if (empty($id)) {
            throw new \InvalidArgumentException('作品ID为必填项.');
        }

        $work = Work::find($id);
        if (!$work) {
            throw new \Exception('作品未找到.');
        }

        $userId = get_user_id();
        if ($work->user_id !== $userId) {
            throw new \Exception('无权修改此作品的状态.');
        }

        $work->is_public = $status;
        $work->save();

        return $work;
    }

    public static function delete($id)
    {
        if (empty($id)) {
            throw new \InvalidArgumentException('作品ID为必填项.');
        }

        $work = Work::find($id);
        if (!$work) {
            throw new \Exception('作品未找到.');
        }

        $userId = get_user_id();
        if ($work->user_id !== $userId) {
            throw new \Exception('无权删除此作品.');
        }

        $work->delete();

        return true;
    }

    public static function createOrder($payWay, $workId, $payWayType = 'h5')
    {
        // Generate a unique order number
        $orderNo = OrderService::generateOrderNo();

        $work = Work::find($workId);

        if (UserWorkService::hasBuy($workId, get_user_id())) {
            throw new \Exception('您已购买过该作品，请勿重复购买.');
        }

        $userWork = UserWork::where('user_id', get_user_id())->where('work_id', $workId)->where('is_pay', 0)->first();

        $isVip = User::where('id', get_user_id())->value('is_vip');
        $vipDiscount = ConfigService::get('vip_discount');

        if (!$userWork) {
            // Create the order
            $orderData = [
                'order_no' => $orderNo,
                'user_id' => get_user_id(),
                'price' => $work['price'], // Example price for upgrading membership
                'type' => Order::TYPE_WORK,
                'pay_way' => $payWay,
                'pay_way_type' => $payWayType,
                'status' => Order::STATUS_WAITING_PAY,
                'created_time' => date('Y-m-d H:i:s'),
            ];

            if ($isVip) {
                $orderData['price'] = bcmul($work['price'], $vipDiscount / 10, 2);
            }

            Order::insert($orderData);

            $userWorkData = [
                'order_no' => $orderNo,
                'user_id' => get_user_id(),
                'work_id' => $workId,
                'work_info' => json_encode($work, JSON_UNESCAPED_UNICODE),
                'created_time' => date('Y-m-d H:i:s'),
                'is_pay' => 0,
                'price' => $orderData['price']
            ];

            UserWork::insert($userWorkData);
        } else {
            $orderNo = $userWork['order_no'];

            $orderData = Order::where('order_no', $orderNo)->first();

            if ($isVip) {
                $orderData['price'] = bcmul($work['price'], $vipDiscount / 10, 2);
            }

            if ($orderData['pay_way'] != $payWay) {
                $orderData['pay_way'] = $payWay;
                $orderData->save();
            }

            $userWork = UserWork::where('order_no', $orderNo)->first();
            $userWork->price = $orderData['price'];
            $userWork->save();
        }

        // Prepare the response
        $response = ['order_no' => $orderNo];

        // If payment method is WeChat, generate WeChat payment parameters
        if ($payWay === Order::PAY_TYPE_WECHAT) {
            $paymentParams = PayFactory::create($payWay)->setData([
                'pay_way_type' => $payWayType,
                'order_no' => $orderNo,
                'total_amount' => $orderData['price'],
            ])->pay();

            $response['payment_params'] = $paymentParams;
        } elseif ($payWay === Order::PAY_TYPE_BALANCE) {
            PayFactory::create($payWay)->setData([
                'order_no' => $orderNo,
                'total_amount' => $orderData['price'],
                'source' => UserPropertyLog::PAY_ORDER
            ])->pay();
        } elseif ($payWay === Order::PAY_TYPE_PAYPAL) {
            throw new \Exception('Paypal 正在接入中');
            $exchangeRate = UserService::getExchangeRate('USD', 'CNY');
            $paymentParams = PayFactory::create($payWay)->setData([
                'pay_way_type' => $payWayType,
                'order_no' => $orderNo,
                'total_amount' => bcdiv($orderData['price'], $exchangeRate, 2),
            ])->pay();

            if ($paymentParams['status'] != 'CREATED') {
                Log::error(var_export($paymentParams, true));
                throw new \Exception('提交到Paypal创建订单失败,请联系管理员');
            }

            Order::where('order_no', $orderNo)->update([
                'paypal_order_id' => $paymentParams['id'],
                'exchange_rate' => $exchangeRate,
            ]);

            $response['links'] = $paymentParams['links'];
        }

        if ($payWay == Order::PAY_TYPE_BALANCE) {
            self::paySuccess($orderNo);
        }

        return $response;
    }

    public static function paySuccess($orderNo)
    {
        $order = Order::where('order_no', $orderNo)->first();

        $order->status = Order::STATUS_FINISH;
        $order->pay_time = date('Y-m-d H:i:s');
        $order->save();

        $userWork = UserWork::where('order_no', $orderNo)->first();
        $userWork->is_pay = 1;


        $work = Work::where('id', $userWork['work_id'])->first();
        $work->sales = $work->sales + 1;
        $work->save();

        $designer = User::where('id', $work['user_id'])->first();

        $rebate = $designer['is_vip'] ? ConfigService::get('designer_rebate_vip') : ConfigService::get('designer_rebate_normal_member');

        $rebate = bcmul($rebate / 100, $order['price'], 2);

        PropertyService::add($designer['id'], PayFactory::COMMISSION, $rebate, UserPropertyLog::REWARD_INCOME, '作品销售分成', $orderNo);

        $newWorkId = UserWorkService::copy($orderNo);

        $userWork->new_work_id = $newWorkId;

        $userWork->save();
    }

}